package com.ocom.payconfig.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ocom.common.dto.payconfig.FeeDataGzhVo;
import com.ocom.common.entity.card.EntityXfRecordProcess;
import com.ocom.common.entity.human.EntityPersonnelInfo;
import com.ocom.common.entity.payconfig.FeeData;
import com.ocom.common.entity.payconfig.FeeItem;
import com.ocom.common.enums.DataSourceEnum;
import com.ocom.common.enums.MasterSlaveEnum;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.payhandle.FeeRefundRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.DateUtils;
import com.ocom.common.utils.RandomUtil;
import com.ocom.common.utils.ResultUtil;
import com.ocom.common.utils.StringUtil;
import com.ocom.common.vo.payconfig.FeeDataByPersonResponse;
import com.ocom.common.vo.payconfig.FeeDataListVo;
import com.ocom.common.vo.payconfig.FeeListVo;
import com.ocom.common.vo.payconfig.PersonRefundVo;
import com.ocom.mysql.aspect.DataSourceAspect;
import com.ocom.payconfig.client.PayhandleClientService;
import com.ocom.payconfig.dao.IDaoFeeData;
import com.ocom.payconfig.service.FeeDataService;
import com.ocom.payconfig.service.FeeItemService;
import com.ocom.payconfig.service.PersonnelInfoService;
import com.ocom.payconfig.service.XfRecordProcessService;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import icu.mhb.mybatisplus.plugln.core.JoinLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 缴费清单 服务实现类
 * </p>
 *
 * @author junShu
 * @since 2023-08-18
 */
@Slf4j
@Service
public class FeeDataServiceImpl extends JoinServiceImpl<IDaoFeeData, FeeData> implements FeeDataService {

    @Resource
    private IDaoFeeData iDaoFeeData;
    @Resource
    private FeeItemService feeItemService;
    @Resource
    private PersonnelInfoService personnelInfoService;
    @Resource
    private PayhandleClientService payhandleClientService;
    @Resource
    private XfRecordProcessService xfRecordProcessService;

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public List<Map<String, Object>> getSumFeeData(Long comId, String strItemID) {
        QueryWrapper<FeeData> query = Wrappers.query();
        query.select("item_id AS itemId, SUM(plan_money) AS planAmount", "SUM(case when plan_money = 0 then 0 else 1 end) AS planNumber ", "SUM(complete_money) AS completeAmount", "SUM(case when complete_money =0  then 0 else 1 end) AS completeNumber", "SUM(refund_money) AS refundAmount", "SUM(case when refund_money = 0 then 0 else 1 end) AS refundNumber");
        query.eq("com_id", comId);
        query.inSql("item_id",  strItemID);
        query.groupBy("item_id");
        List<Map<String, Object>> sumFeeDataVo = this.listMaps(query);
//        System.out.println("sumFeeDataVo==="+sumFeeDataVo);
//        if(sumFeeDataVo.size() > 0){
//           return sumFeeDataVo.get(0);
//        }
        return sumFeeDataVo;
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Result feeDataList(Long comId,FeeDataListVo request) {
        if (request.getPage() == null || request.getSize() == null || request.getPage() == -1 || request.getSize() == -1) {
            request.setPage(1);
            request.setSize(500);
        }
        if (StringUtil.isNotEmpty(request.getDeptIds())) {
            String[] strDeptId;
            if (request.getDeptIds().contains(",")) {
                strDeptId = request.getDeptIds().split(",");
            } else {
                strDeptId = new String[]{request.getDeptIds()};
            }
            request.setDeptIdArray(strDeptId);
        }
        PageHelper.startPage(request.getPage(), request.getSize());
        List<FeeListVo> listFeeData = iDaoFeeData.feeDataList(request);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo(listFeeData);
        HashMap<String, Object> mapFeeData = new HashMap();
        mapFeeData.put("list", listFeeData);
        mapFeeData.put("total", pageInfo.getTotal());
        return ResultUtil.success(mapFeeData);
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId", isMaster = MasterSlaveEnum.MASTER)
    public Result addFeeData(Long comId, FeeDataListVo request) {
        List<Map<String, Object>> listPId = null;
        if (request.getAccType() == null || request.getAccType() == 0) {
            QueryWrapper<FeeData> query = Wrappers.query();
            query.select("p_id", "dept_id");
            query.eq("com_id", comId);
            if (StringUtil.isNotEmpty(request.getPCode())) {
                query.eq("p_code", request.getPCode());
            }
            if (StringUtil.isNotEmpty(request.getPName())) {
                query.like("p_name", request.getPName());
            }
//            if (StringUtil.isNotEmpty(request.getDeptIds())) {
//                query.inSql("dept_id", request.getDeptIds());
//            }
            if (request.getDeptId() != 0) {
                query.eq("dept_id", request.getDeptId());
            }
            listPId = personnelInfoService.selectPersonByFee(comId,request.getDeptId(),request.getPCode(),request.getPName());
            if (listPId.size() == 0) {
                return ResultUtil.error(ResultEnum.Err_2020);
            }
        } else if (request.getAccType() > 0) {
            int[] strDeptId = null;
//            if (StringUtil.isNotEmpty(request.getDeptIds())) {
//                if (request.getDeptIds().contains(",")) {
//                    strDeptId = request.getDeptIds().split(",");
//                } else {
//                    strDeptId = new String[]{request.getDeptIds()};
//                }
//                request.setDeptIdArray(strDeptId);
//            }
            if(request.getDeptId() != 0){
                strDeptId = new int[]{request.getDeptId()};
            }
            listPId = iDaoFeeData.selectByPId(comId, request.getAccType(), strDeptId);
            if (listPId.size() == 0) {
                return ResultUtil.error(ResultEnum.Err_2020);
            }
        }
//        System.out.println("listPId==="+listPId);
        ArrayList<FeeData> listFeeData = new ArrayList<>();
        for (Map<String, Object> map : listPId) {
//            System.out.println("listPId==="+map.get("p_id"));
            FeeData feeData = new FeeData();
            feeData.setComId(request.getComId());
            feeData.setItemId(request.getFeeItemId());
            feeData.setDataStatus(1);
            feeData.setPId(Integer.parseInt(String.valueOf(map.get("pId"))));
            Object oDeptId = map.get("deptId");
            if(oDeptId == null){
                feeData.setDeptId(0);
            }else{
                feeData.setDeptId(Integer.parseInt(String.valueOf(oDeptId)));
            }
            feeData.setPlanMoney(request.getPlanMoney());
            feeData.setOrderNo("JF" + String.format("%08d", request.getFeeItemId()) + "P" + String.format("%08d", feeData.getPId()));
            feeData.setCompleteMoney(0);
            feeData.setRefundMoney(0);
            listFeeData.add(feeData);
        }
        boolean bSave = this.saveBatch(listFeeData, 1000);
        return ResultUtil.success(bSave);
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId", isMaster = MasterSlaveEnum.MASTER)
    public Result updateFeeMoney(Long comId,FeeDataListVo request) {
        FeeItem item = feeItemService.getByStatus(request.getComId(), request.getFeeItemId());
        if (item == null) {
            return ResultUtil.error(ResultEnum.Err_4133);
        }
        UpdateWrapper<FeeData> update = Wrappers.update();
        update.eq("com_id ", comId);
        update.eq("item_id ", request.getFeeItemId());
        update.eq("data_status", 1);
        update.inSql("p_id", request.getPIds());
        update.ne("plan_money", request.getPlanMoney());
        update.set("plan_money", request.getPlanMoney());
        update.set("update_time", LocalDateTime.now());
        update.set("update_userid", request.getUpdateUserid());
        return ResultUtil.success(this.update(update));
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId", isMaster = MasterSlaveEnum.MASTER)
    public Result removeFeeData(Long comId,FeeDataListVo request) {
        FeeItem item = feeItemService.getByStatus(request.getComId(), request.getFeeItemId());
        if (item == null) {
            return ResultUtil.error(ResultEnum.Err_4133);
        }
        UpdateWrapper<FeeData> update = Wrappers.update();
        update.eq("com_id ", comId);
        update.eq("data_status", 1);
        update.eq("item_id", request.getFeeItemId());
        update.inSql("p_id", request.getPIds());
        return ResultUtil.success(this.remove(update));
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId", isMaster = MasterSlaveEnum.MASTER)
    public Result addFeeDataByPerson(Long comId,FeeDataListVo request) {
        EntityPersonnelInfo personnel = null;
        if (request.getPId() == 0) {
            personnel = personnelInfoService.getDataByPerson(request.getComId(), request.getPCode());
            if (personnel == null) {
                return ResultUtil.error(ResultEnum.Err_303);
            }
        }
        String orderNo = "JF" + String.format("%08d", request.getFeeItemId()) + "P" + String.format("%08d", personnel.getPId());
        QueryWrapper<FeeData> query = Wrappers.query();
        query.eq("com_id", request.getComId());
        query.eq("order_no", orderNo);
        query.last("Limit 1");
        FeeData getFeeData = this.getOne(query);
        boolean bUpdate;
        if(getFeeData != null){
            UpdateWrapper<FeeData> update = Wrappers.update();
            update.eq("com_id", request.getComId());
            update.eq("order_no", orderNo);
            update.set("plan_money", request.getPlanMoney());
            bUpdate = this.update(update);
        }else{
            FeeData feeData = new FeeData();
            feeData.setComId(request.getComId());
            feeData.setItemId(request.getFeeItemId());
            feeData.setDataStatus(1);
            feeData.setPId(Integer.parseInt(String.valueOf(personnel.getPId())));
            feeData.setDeptId(Integer.parseInt(String.valueOf(personnel.getDeptId())));
            feeData.setPlanMoney(request.getPlanMoney());
            feeData.setOrderNo(orderNo);
            bUpdate = this.save(feeData);
        }
        return ResultUtil.success(bUpdate);
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public HashMap<String, Object> feeDataByPerson(Long comId,FeeDataListVo request){
        if (request.getPage() == null || request.getSize() == null || request.getPage() == -1 || request.getSize() == -1) {
            request.setPage(1);
            request.setSize(100);
        }
        PageHelper.startPage(request.getPage(), request.getSize());
//        System.out.println("request.getDataStatus()==="+request.getDataStatus());
        List<FeeDataByPersonResponse> listPersonData = iDaoFeeData.feeDataByPerson(comId,request.getPId(), request.getFeeItemId(),request.getDataStatus());
        PageInfo<Map<String, Object>> pageInfo = new PageInfo(listPersonData);
        HashMap<String, Object> mapFeeData = new HashMap();
        mapFeeData.put("list", listPersonData);
        mapFeeData.put("total", pageInfo.getTotal());
        return mapFeeData;
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Result personRefund(Long comId, PersonRefundVo request){
        FeeDataListVo feeData = new FeeDataListVo();
        feeData.setPage(1);
        feeData.setSize(1);
        feeData.setComId(comId);
        feeData.setFeeItemId(request.getFeeItemId());
        feeData.setDataStatus(4);
        String[] strPIds = null;
        if(StringUtil.isNotEmpty(request.getPIds())){
            if(request.getPIds().contains(",")){
                strPIds = request.getPIds().split(",");
            }else{
                feeData.setPId(Integer.parseInt(request.getPIds()));
            }
        }
        Result result = null;
        if(strPIds != null && strPIds.length >0){
            for(String sPId: strPIds){
                feeData.setPId(Integer.parseInt(sPId));
                try{
                    result = feeRefund(comId,feeData,request.getRefundMoney());
                }catch (Exception e){
                    e.printStackTrace();
                    log.info("缴费退费异常 pIds : {}" +  sPId);
                }
            }
        }else{
            try{
                result = feeRefund(comId,feeData,request.getRefundMoney());
            }catch (Exception e){
                e.printStackTrace();
                log.info("缴费退费异常 pIds : {}" +  feeData.getPId());
            }
        }
        return result;
    }



    private Result feeRefund(Long comId, FeeDataListVo feeData,int refundMoney) throws JsonProcessingException {
        HashMap<String, Object> mapFeeData = feeDataByPerson(comId, feeData);
        if(mapFeeData.isEmpty()){
            return new Result(4017,"未找到该人员,pId: " + feeData.getPId(),"");
        }
        List<Map<String, Object>> listPersonData = new ObjectMapper().readValue(JSON.toJSONString(mapFeeData.get("list")), List.class);;
//        List<Map<String, Object>> listPersonData = (List)JSON.parseArray(JSON.toJSONString(mapFeeData.get("list")), List.class);
//        System.out.println("mapFeeData=="+listPersonData);
//        System.out.println("mapFeeData.get(\"list\")=="+mapFeeData.get("list"));
        if(listPersonData == null || listPersonData.isEmpty()){
            return new Result(4017,"返回数组未找到该人员,pId: " + feeData.getPId(),"");
        }
        Map<String, Object> getFee = listPersonData.get(0);
        String orderNo = String.valueOf(getFee.get("orderNo"));
        String tradeNo = String.valueOf(getFee.get("tradeNo"));
        if(null == getFee.get("tradeNo") || StringUtils.isBlank(tradeNo)){
            return new Result(500,"未查询到支付成功订单号,orderNo: " + orderNo,"");
        }
        FeeRefundRequest feeRefund = new FeeRefundRequest();
        feeRefund.setCompanyId(comId);
        feeRefund.setFeeItemId(feeData.getFeeItemId());
        feeRefund.setPId(feeData.getPId());
        feeRefund.setRefundAmount(refundMoney);
        feeRefund.setOrigTradeNo(tradeNo);
        feeRefund.setTradeNo("TF"+ RandomUtil.getRandomString(30));
        Result result = payhandleClientService.feeRefund(feeRefund);
        if(result.getCode()== 200){
            boolean updateFeeStatus = updateFeeStatus(comId, orderNo,5,refundMoney,feeRefund.getTradeNo());
            return ResultUtil.success(updateFeeStatus);
        }else{
            updateFeeStatus(comId, orderNo,0,refundMoney,null);//status不支持负数
            return result;
        }
//        return result;
    }
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId", isMaster = MasterSlaveEnum.MASTER)
    public Boolean updateFeeStatus(Long comId, String order_no, int DataStatus,int refundMoney,String refundOrderNo) {
        UpdateWrapper<FeeData> update = Wrappers.update();
        update.eq("com_id ", comId);
        update.eq("order_no ", order_no);
        update.eq("data_status ", 4);
        update.set("refund_money",refundMoney);
        if (refundOrderNo != null) {
            update.set("refund_order_no", refundOrderNo);
        }
        if (DataStatus == 5) {
            update.set("refund_time", new Date());
        }
        update.set("data_status",DataStatus);
        update.set("fee_time", LocalDateTime.now());
        update.set("update_time", LocalDateTime.now());
        update.set("update_userid", 888);
        return this.update(update);
    }


    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, isMaster = MasterSlaveEnum.MASTER)
    public boolean addFeeDataOne(Long companyId, FeeData feeData) {

   //     String dateStr = DateUtils.getStrDate(new Date(), "MMdd");
        String dateStr = "2025";

        feeData.setDataStatus(1);
        feeData.setOrderNo("JF" + String.format("%08d", feeData.getItemId()) + "P" + String.format("%08d", feeData.getPId())+ "D" +dateStr);
        feeData.setCompleteMoney(0);
        feeData.setRefundMoney(0);
        return this.save(feeData);
    }


    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    @DataSourceAspect(type = DataSourceEnum.PART_DB, isMaster = MasterSlaveEnum.MASTER)
    public boolean addFeeDataFree(Long companyId, FeeData feeData, EntityXfRecordProcess entityXfRecordProcess) {

//        String dateStr = DateUtils.getStrDate(new Date(), "MMdd");
        String dateStr = "2025";

        feeData.setDataStatus(4);
        feeData.setOrderNo("JF" + String.format("%08d", feeData.getItemId()) + "P" + String.format("%08d", feeData.getPId()) + "D" + dateStr);
        feeData.setRefundMoney(0);
        boolean sz = this.save(feeData);
        if (!sz) {
            throw new RuntimeException("插入失败1");
        }

        entityXfRecordProcess.setReserved2(feeData.getId().toString());
        int sz4 = xfRecordProcessService.insertEntityXfRecord(companyId, entityXfRecordProcess);

        if (sz4 == 0) {
            throw new RuntimeException("插入失败2");
        }

        //TODO  插入成功单
        return true;
    }



    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, isMaster = MasterSlaveEnum.SLAVE)
    public Page<FeeDataGzhVo> getItemDateGzh(Long companyId, Integer page, Integer size) {
        JoinLambdaWrapper<FeeData> queryWrapper = new JoinLambdaWrapper<>(FeeData.class);
        queryWrapper.eq(FeeData::getComId, companyId);
        queryWrapper.eq(FeeData::getDataStatus, 1);
        queryWrapper.apply("DATE_SUB(CURDATE(), INTERVAL 2 DAY) <=date(fee_data.create_time)");
        queryWrapper.orderByAsc(FeeData::getCreateTime);
    //    queryWrapper.select(FeeData::getComId,FeeData::getPlanMoney,FeeData::getItemId,FeeData::getPId,FeeData::getOrderNo);
        queryWrapper.selectAs((cb) -> {
            cb.add(" fee_data.com_id ","comId",false);
            cb.add(" fee_data.p_id ","pId",false);
            cb.add(" fee_data.item_id ","itemId",false);
            cb.add(" fee_data.plan_money ","planMoney",false);
            cb.add(" fee_data.order_no ","orderNo",false);
        });
        queryWrapper.leftJoin(EntityPersonnelInfo.class,  EntityPersonnelInfo::getPId, FeeData::getPId, "personnel_info")
                .eq(EntityPersonnelInfo::getStatus,0)
                .selectAs((cb) -> {
                    cb.add(" personnel_info.p_name ","pName",false);
                    cb.add(" personnel_info.p_code ","pCode",false);
                })
                .end();
        queryWrapper.leftJoin(FeeItem.class,  FeeItem::getItemId,FeeData::getItemId, "fee_item")
                .eq(FeeItem::getStatus,2)
                .selectAs((cb) -> {
                    cb.add(" fee_item.item_name ","itemName",false);
                    cb.add(" fee_item.stop_date ","stopDate",false);
                })
                .end();
        Page<FeeDataGzhVo> page1 = new Page<>(page, size);
        return this.joinPage(page1,queryWrapper, FeeDataGzhVo.class);
    }

}
